#include "usart1.h"

UART_HandleTypeDef huart1;

uint16_t u1RxLen                = 0;
uint8_t u1RxBuf[USART1_RX_SIZE] = {0};

extern void Error_Handler(void);

void _usart1_rx_callback(struct __UART_HandleTypeDef *huart, uint16_t Pos)
{
    if (huart->Instance == USART1) {
        u1RxLen = Pos; // 本次接收的实际数据长度是多少

        // 需要在再次开启接收
        HAL_UARTEx_ReceiveToIdle_IT(huart, u1RxBuf, USART1_RX_SIZE);
    }
}

void usart1_init(int bound)
{

#ifdef USE_HAL_DRIVER
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_AFIO_CLK_ENABLE(); // 复用功能的时钟

    {
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        /**USART1 GPIO Configuration
            PA9     ------> USART1_TX
            PA10     ------> USART1_RX
        */
        GPIO_InitStruct.Pin   = GPIO_PIN_9; // PA9，复用输出模式
        GPIO_InitStruct.Mode  = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin  = GPIO_PIN_10; // PA10,输入模式，
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL; // 浮空输入（推荐上拉或者浮空）
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    huart1.Instance          = USART1;               // 实例对象 USART1
    huart1.Init.BaudRate     = bound;                // 波特率
    huart1.Init.WordLength   = UART_WORDLENGTH_8B;   // 数据位宽度
    huart1.Init.StopBits     = UART_STOPBITS_1;      // 停止位
    huart1.Init.Parity       = UART_PARITY_NONE;     // 是否使用校验位
    huart1.Init.Mode         = UART_MODE_TX_RX;      // 同时支持数据接收和发送
    huart1.Init.HwFlowCtl    = UART_HWCONTROL_NONE;  // 是否使用硬件控制流
    huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 溢出 不用
    if (HAL_UART_Init(&huart1) != HAL_OK) {
        Error_Handler();
    }

    // 开启NVIC
    HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

    // 注册接收完成回调函数
    HAL_UART_RegisterRxEventCallback(&huart1, _usart1_rx_callback);
    // HAL_UART_RegisterCallback

    // 开启接收中断（开启接收到空闲中断）
    HAL_UARTEx_ReceiveToIdle_IT(&huart1, u1RxBuf, USART1_RX_SIZE); // 这个函数，只会成功接收一次，
#else

#endif
}

/**
 * @brief This function handles USART1 global interrupt.
 */
void USART1_IRQHandler(void)
{
    HAL_UART_IRQHandler(&huart1);
}

// 当发现以上另种方式，无法正常工作的时候，推荐使用printf.c源码进行
// #include "printf.h"

void _putchars(char *buf, short len)
{
    // 将来，如果使用DMA的方式，可以极大提高发送效率
    int i = 0;
    for (i = 0; i < len; i++) {
        // 只有在发送寄存器为空的时候，才可以设置DR寄存器
        while ((USART1->SR & (1 << 7)) == 0x00)
            ;
        USART1->DR = buf[i];
    }

    // 非常重要！！！
    while ((USART1->SR & (1 << 6)) == 0x00)
        ;
}

void usart1_tx(uint8_t *buf, uint16_t len)
{
    if (HAL_UART_Transmit(&huart1, buf, len, 0xFFF) != HAL_OK) {
        Error_Handler();
    }
}